#include "UartChannel.h"
#include <iostream>

UartChannel::UartChannel(const std::string& portName, int baudRate)
    : portName(portName), baudRate(baudRate), isOpen(false), isRunning(false) {}

UartChannel::~UartChannel() {
    close();
}

bool UartChannel::open() {
    std::lock_guard<std::mutex> lock(mutex);
    if (isOpen) return true;

    if (serialPort.init(portName.c_str(), baudRate) && serialPort.open()) {
        isOpen = true;
        isRunning = true;
        receiveThread = std::thread(&UartChannel::receiveData, this);
        return true;
    }
    return false;
}

void UartChannel::close() {
    std::lock_guard<std::mutex> lock(mutex);
    if (!isOpen) return;

    isRunning = false;
    if (receiveThread.joinable()) {
        receiveThread.join();
    }
    serialPort.close();
    isOpen = false;

    // 通知状态回调
    if (statusCallback) {
        statusCallback(false); // 通知掉线
    }
}

bool UartChannel::send(const std::string& data) {
    std::lock_guard<std::mutex> lock(mutex);
    if (!isOpen) return false;

    bool result = serialPort.writeData(data.c_str(), data.size());
    if (!result) {
        // 发送失败，可能是掉线
        close();
        return false;
    }
    return true;
}

void UartChannel::setReceiveCallback(ReceiveCallback callback) {
    std::lock_guard<std::mutex> lock(mutex);
    receiveCallback = callback;
}

void UartChannel::setStatusCallback(StatusCallback callback) {
    std::lock_guard<std::mutex> lock(mutex);
    statusCallback = callback;
}

bool UartChannel::isConnected() const {
    return isOpen;
}

void UartChannel::receiveData() {
    char buffer[1024];
    while (isRunning) {
        int bytesRead = serialPort.readData(buffer, sizeof(buffer));
        if (bytesRead > 0) {
            std::string receivedData(buffer, bytesRead);
            if (receiveCallback) {
                receiveCallback(receivedData);
            }
        } else if (bytesRead < 0) {
            // 读取失败，可能是掉线
            close();
            break;
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
}